<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>标签设计器</title>
    <!-- 引入Element UI样式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入二维码生成库 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
    <!-- 引入条形码生成库 -->
    <script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/JsBarcode.all.min.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
            background-color: #f5f5f5;
            overflow: hidden;
        }

        .container {
            display: flex;
            height: 100vh;
            overflow: hidden;
        }

        /* 左侧工具栏 */
        .toolbar {
            width: 250px;
            background-color: white;
            border-right: 1px solid #e9ecef;
            padding: 20px;
            overflow-y: auto;
            flex-shrink: 0;
        }

        .toolbar-section {
            margin-bottom: 25px;
        }

        .toolbar-title {
            font-size: 16px;
            font-weight: 600;
            color: #2c3e50;
            margin-bottom: 15px;
            padding-bottom: 8px;
            border-bottom: 1px solid #e9ecef;
        }

        .element-item {
            padding: 10px 15px;
            background-color: #f8f9fa;
            border: 1px solid #e9ecef;
            border-radius: 4px;
            margin-bottom: 10px;
            cursor: grab;
            transition: all 0.2s;
            display: flex;
            align-items: center;
        }

        .element-item:hover {
            background-color: #e9ecef;
            border-color: #409eff;
        }

        .element-icon {
            margin-right: 10px;
            font-size: 18px;
        }

        .element-name {
            font-size: 14px;
            color: #2c3e50;
        }

        /* 中间设计区域 */
        .design-area {
            flex: 1;
            display: flex;
            flex-direction: column;
            overflow: hidden;
            background-color: #f0f2f5;
            padding: 20px;
        }

        .design-header {
            background-color: white;
            padding: 15px 20px;
            border-radius: 4px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
            margin-bottom: 20px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .design-title {
            font-size: 18px;
            font-weight: 600;
            color: #2c3e50;
        }

        .design-actions {
            display: flex;
            gap: 10px;
        }

        .canvas-container {
            flex: 1;
            display: flex;
            justify-content: center;
            align-items: flex-start;
            overflow: auto;
            padding: 20px;
        }

        .label-canvas {
            background-color: white;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
            position: relative;
            width: 100mm;
            height: 60mm;
            border: 1px solid #ddd;
            user-select: none;
            /* 禁止文本选择 */
            -webkit-user-select: none;
            /* Safari兼容 */
            -moz-user-select: none;
            /* Firefox兼容 */
            -ms-user-select: none;
            /* IE兼容 */
        }

        .label-element {
            position: absolute;
            cursor: move;
            border: 0px solid #000;
            padding: 0px;
            box-sizing: border-box;
            transform-origin: top left;
            user-select: none;
            /* 禁止文本选择 */
            -webkit-user-select: none;
            /* Safari兼容 */
            -moz-user-select: none;
            /* Firefox兼容 */
            -ms-user-select: none;
            /* IE兼容 */
        }

        .label-element:hover {
            border: 1px dashed #409eff;
        }

        .label-element.selected {
            border: 1px solid #409eff;
            /* box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2); */
        }

        /* 缩放手柄 */
        .resize-handle {
            position: absolute;
            width: 6px;
            height: 6px;
            background-color: #409eff;
            border: 1px solid white;
            border-radius: 50%;
            z-index: 10;
            display: none;
        }

        .label-element.selected .resize-handle {
            display: block;
        }

        .resize-handle-nw {
            top: -2px;
            left: -2px;
            cursor: nw-resize;
        }

        .resize-handle-ne {
            top: -2px;
            right: -2px;
            cursor: ne-resize;
        }

        .resize-handle-sw {
            bottom: -2px;
            left: -2px;
            cursor: sw-resize;
        }

        .resize-handle-se {
            bottom: -2px;
            right: -2px;
            cursor: se-resize;
        }

        .element-label {
            color: #333;
        }

        .element-qrcode {
            background-color: #f0f9eb;
            border: 1px solid #c2e7b0;
            padding: 3px;
            box-sizing: border-box;
        }

        .element-barcode {
            background-color: #f0f9eb;
            border: 1px solid #c2e7b0;
        }

        /* 右侧属性面板 */
        .property-panel {
            width: 300px;
            background-color: white;
            border-left: 1px solid #e9ecef;
            padding: 20px;
            overflow-y: auto;
            flex-shrink: 0;
        }

        .property-section {
            margin-bottom: 20px;
        }

        .property-title {
            font-size: 14px;
            font-weight: 600;
            color: #2c3e50;
            margin-bottom: 12px;
        }

        .property-item {
            margin-bottom: 15px;
        }

        .property-label {
            display: block;
            font-size: 13px;
            color: #606266;
            margin-bottom: 5px;
        }

        .el-input,
        .el-select {
            width: 100%;
        }

        .dimension-info {
            font-size: 13px;
            color: #909399;
            margin-top: 5px;
        }

        /* 底部状态栏 */
        .status-bar {
            height: 30px;
            background-color: #f8f9fa;
            border-top: 1px solid #e9ecef;
            display: flex;
            align-items: center;
            padding: 0 20px;
            font-size: 12px;
            color: #606266;
        }

        /* 拖拽时的样式 */
        .dragging {
            opacity: 0.7;
            transform: rotate(5deg);
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="container">
            <!-- 左侧工具栏 -->
            <div class="toolbar">
                <div class="toolbar-section">
                    <div class="toolbar-title">基础元素</div>
                    <div class="element-item" draggable="true" data-type="label">
                        <span class="element-icon">📝</span>
                        <span class="element-name">文本标签</span>
                    </div>
                    <div class="element-item" draggable="true" data-type="qrcode">
                        <span class="element-icon">🔲</span>
                        <span class="element-name">二维码</span>
                    </div>
                    <div class="element-item" draggable="true" data-type="barcode">
                        <span class="element-icon">📊</span>
                        <span class="element-name">条形码</span>
                    </div>
                    <div class="element-item" draggable="true" data-type="rectangle">
                        <span class="element-icon">▭</span>
                        <span class="element-name">矩形</span>
                    </div>
                </div>

                <div class="toolbar-section">
                    <div class="toolbar-title">操作</div>
                    <el-button type="danger" icon="el-icon-delete" size="small"
                        style="width: 100%; margin-bottom: 10px;" @click="clearCanvas">
                        清空画布
                    </el-button>
                    <el-button type="primary" icon="el-icon-download" size="small" style="width: 100%;margin-left: 0px;"
                        @click="exportLayout">
                        导出布局
                    </el-button>
                </div>

                <div class="toolbar-section">
                    <div class="toolbar-title">导入布局</div>
                    <el-upload action="#" :auto-upload="false" :on-change="importLayout" accept=".json">
                        <el-button size="small" type="success" icon="el-icon-upload2">
                            选择JSON文件
                        </el-button>
                    </el-upload>
                </div>
            </div>

            <!-- 中间设计区域 -->
            <div class="design-area">
                <div class="design-header">
                    <div class="design-title">标签设计器 ({{canvasWidth}} × {{canvasHeight}})</div>
                    <div class="design-actions">
                        <el-button type="primary" icon="el-icon-zoom-in" size="small" @click="zoomIn">放大</el-button>
                        <el-button type="primary" icon="el-icon-zoom-out" size="small" @click="zoomOut">缩小</el-button>
                        <el-button type="primary" icon="el-icon-rank" size="small" @click="resetZoom">重置缩放</el-button>
                    </div>
                </div>

                <div class="canvas-container">
                    <div class="label-canvas" id="labelCanvas" ref="labelCanvas" @drop="dropElement"
                        @dragover="allowDrop" @click="deselectElement"
                        :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }">
                        <!-- 动态生成的元素将在这里显示 -->
                        <div v-for="element in elements" :key="element.id" class="label-element"
                            :class="{'selected': selectedElementId === element.id}" :style="getElementStyle(element)"
                            @mousedown="selectElement(element.id, $event)" @dblclick="editElement(element)">
                            <div v-if="element.type === 'label'" class="element-label">{{ element.text || '文本标签' }}
                            </div>
                            <div v-else-if="element.type === 'qrcode'" class="element-qrcode">
                                <div :ref="'qrcode_' + element.id" style="width:100%; height:100%;"></div>
                            </div>
                            <div v-else-if="element.type === 'barcode'" class="element-barcode">
                                <svg :ref="'barcode_' + element.id" style="width:100%; height:100%;"></svg>
                            </div>
                            <div v-else-if="element.type === 'rectangle'" class="element-rectangle"
                                :style="{width: '100%', height: '100%', backgroundColor: element.backgroundColor || '#000000'}">
                            </div>
                            <!-- 缩放手柄 -->
                            <div class="resize-handle resize-handle-nw"
                                @mousedown.stop="startResize(element.id, 'nw', $event)"></div>
                            <div class="resize-handle resize-handle-ne"
                                @mousedown.stop="startResize(element.id, 'ne', $event)"></div>
                            <div class="resize-handle resize-handle-sw"
                                @mousedown.stop="startResize(element.id, 'sw', $event)"></div>
                            <div class="resize-handle resize-handle-se"
                                @mousedown.stop="startResize(element.id, 'se', $event)"></div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 右侧属性面板 -->
            <div class="property-panel">
                <div class="property-section" v-if="selectedElement">
                    <div class="property-title">元素属性</div>

                    <div class="property-item">
                        <label class="property-label">元素类型</label>
                        <el-input v-model="selectedElement.type" readonly></el-input>
                    </div>

                    <div class="property-item" v-if="selectedElement.type === 'label'">
                        <label class="property-label">文本内容</label>
                        <el-input v-model="selectedElement.text" placeholder="请输入文本内容"></el-input>
                    </div>

                    <div class="property-item">
                        <label class="property-label">左边距 (px)</label>
                        <el-input-number v-model="selectedElement.x" :min="0" :max="canvasWidth" :step="1"
                            :precision="0" style="width: 100%;"></el-input-number>
                    </div>

                    <div class="property-item">
                        <label class="property-label">上边距 (px)</label>
                        <el-input-number v-model="selectedElement.y" :min="0" :max="canvasHeight" :step="1"
                            :precision="0" style="width: 100%;"></el-input-number>
                    </div>

                    <div class="property-item">
                        <label class="property-label">宽度 (px)</label>
                        <el-input-number v-model="selectedElement.width" :min="1" :max="canvasWidth" :step="1"
                            :precision="0" style="width: 100%;"></el-input-number>
                    </div>

                    <div class="property-item">
                        <label class="property-label">高度 (px)</label>
                        <el-input-number v-model="selectedElement.height" :min="1" :max="canvasHeight" :step="1"
                            :precision="0" style="width: 100%;"></el-input-number>
                    </div>
                    <!-- 
                    <div class="property-item">
                        <label class="property-label">缩放比例</label>
                        <el-slider v-model="selectedElement.scale" :min="0.1" :max="3" :step="0.1" show-input
                            style="width: 100%;"></el-slider>
                        <el-button size="mini" @click="resetElementScale" style="margin-top: 5px;">重置缩放</el-button>
                    </div> -->

                    <div class="property-item" v-if="selectedElement.type === 'label'">
                        <label class="property-label">字体大小 (px)</label>
                        <el-input-number v-model="selectedElement.fontSize" :min="8" :max="72" :step="1" :precision="0"
                            style="width: 100%;"></el-input-number>
                    </div>

                    <div class="property-item" v-if="selectedElement.type === 'label'">
                        <label class="property-label">字体族</label>
                        <el-select v-model="selectedElement.fontFamily" placeholder="请选择字体族">
                            <el-option label="默认" value=""></el-option>
                            <el-option label="微软雅黑" value="微软雅黑, Microsoft YaHei"></el-option>
                            <el-option label="宋体" value="宋体, SimSun"></el-option>
                            <el-option label="黑体" value="黑体, SimHei"></el-option>
                            <el-option label="Arial" value="Arial"></el-option>
                            <el-option label="Helvetica" value="Helvetica"></el-option>
                            <el-option label="Times New Roman" value="Times New Roman"></el-option>
                        </el-select>
                    </div>

                    <div class="property-item" v-if="selectedElement.type === 'label'">
                        <label class="property-label">字体样式</label>
                        <el-checkbox v-model="selectedElement.fontBold">粗体</el-checkbox>
                        <el-checkbox v-model="selectedElement.fontItalic">斜体</el-checkbox>
                    </div>

                    <div class="property-item" v-if="selectedElement.type === 'qrcode'">
                        <label class="property-label">二维码内容</label>
                        <el-input v-model="selectedElement.content" placeholder="请输入二维码内容"
                            @change="generateCodes"></el-input>
                    </div>

                    <div class="property-item" v-if="selectedElement.type === 'barcode'">
                        <label class="property-label">条形码内容</label>
                        <el-input v-model="selectedElement.content" placeholder="请输入条形码内容"
                            @change="generateCodes"></el-input>
                    </div>

                    <div class="property-item" v-if="selectedElement.type === 'barcode'">
                        <label class="property-label">条形码格式</label>
                        <el-select v-model="selectedElement.format" placeholder="请选择条形码格式" @change="generateCodes">
                            <el-option label="CODE128" value="CODE128"></el-option>
                            <el-option label="CODE39" value="CODE39"></el-option>
                            <el-option label="EAN13" value="EAN13"></el-option>
                            <el-option label="EAN8" value="EAN8"></el-option>
                            <el-option label="UPC" value="UPC"></el-option>
                            <el-option label="ITF" value="ITF"></el-option>
                        </el-select>
                    </div>

                    <div class="property-item" v-if="selectedElement.type === 'rectangle'">
                        <label class="property-label">背景颜色</label>
                        <el-color-picker v-model="selectedElement.backgroundColor" size="small"></el-color-picker>
                    </div>

                    <div class="property-item">
                        <el-button type="danger" icon="el-icon-delete" size="small" style="width: 100%;"
                            @click="deleteElement">
                            删除元素
                        </el-button>
                    </div>
                </div>

                <div class="property-section" v-else>
                    <div class="property-title">画布属性</div>
                    <div class="property-item">
                        <label class="property-label">画布宽度 (px)</label>
                        <el-input-number v-model="canvasWidth" :min="10" :max="1000" :step="1"
                            style="width: 100%;"></el-input-number>
                    </div>
                    <div class="property-item">
                        <label class="property-label">画布高度 (px)</label>
                        <el-input-number v-model="canvasHeight" :min="10" :max="1000" :step="1"
                            style="width: 100%;"></el-input-number>
                    </div>
                    <div class="property-item">
                        <label class="property-label">当前尺寸</label>
                        <el-input :value="canvasWidth + 'px × ' + canvasHeight + 'px'" readonly></el-input>
                    </div>
                    <div class="property-item">
                        <label class="property-label">元素数量</label>
                        <el-input :value="elements.length + ' 个'" readonly></el-input>
                    </div>
                </div>
            </div>
        </div>

        <!-- 底部状态栏 -->
        <div class="status-bar">
            <span>就绪</span>
        </div>
    </div>

    <!-- 引入Vue.js -->
    <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
    <!-- 引入Element UI -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <!-- 引入FileSaver.js用于文件下载 -->
    <script src="https://cdn.jsdelivr.net/npm/file-saver@2.0.5/dist/FileSaver.min.js"></script>

    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    elements: [],
                    selectedElementId: null,
                    zoomLevel: 1,
                    elementCounter: 1,
                    canvasWidth: 800, // 画布宽度(mm)
                    canvasHeight: 520, // 画布高度(mm)
                    canvasSizeDialogVisible: false, // 画布尺寸对话框可见性
                    clipboardElement: null // 剪贴板元素
                }
            },

            computed: {
                selectedElement() {
                    return this.elements.find(el => el.id === this.selectedElementId) || null;
                }
            },

            mounted() {
                // 添加拖拽事件监听
                this.addDragListeners();

                // 添加键盘事件监听
                document.addEventListener('keydown', this.handleKeyDown);
            },

            updated() {
                // 在每次更新后重新生成二维码和条形码
                this.$nextTick(() => {
                    this.generateCodes();
                });
            },

            beforeDestroy() {
                document.removeEventListener('keydown', this.handleKeyDown);
            },

            methods: {
                // 添加拖拽监听器
                addDragListeners() {
                    const elementItems = document.querySelectorAll('.element-item');
                    elementItems.forEach(item => {
                        item.addEventListener('dragstart', (e) => {
                            const type = item.getAttribute('data-type');
                            e.dataTransfer.setData('elementType', type);
                            item.classList.add('dragging');
                        });

                        item.addEventListener('dragend', (e) => {
                            item.classList.remove('dragging');
                        });
                    });
                },

                // 生成二维码和条形码
                generateCodes() {
                    this.elements.forEach(element => {
                        if (element.type === 'qrcode') {
                            const canvasContainer = this.$refs['qrcode_' + element.id];
                            if (canvasContainer && canvasContainer.length > 0) {
                                // 清空容器
                                canvasContainer[0].innerHTML = '';

                                // 生成二维码
                                new QRCode(canvasContainer[0], {
                                    text: element.content || 'https://example.com',
                                    width: element.width - 10,
                                    height: element.height - 10,
                                    colorDark: "#000000",
                                    colorLight: "#ffffff",
                                    correctLevel: QRCode.CorrectLevel.H
                                });
                            }
                        } else if (element.type === 'barcode') {
                            const svg = this.$refs['barcode_' + element.id];
                            if (svg && svg.length > 0) {
                                JsBarcode(svg[0], element.content || '1234567890', {
                                    format: element.format || 'CODE128',
                                    width: 2,
                                    height: element.height - 27,
                                    displayValue: false
                                });
                            }
                        }
                    });
                },

                // 允许放置
                allowDrop(e) {
                    e.preventDefault();
                },

                // 取消元素选择
                deselectElement(e) {
                    // 只有当点击的是画布本身而不是元素时才取消选择
                    if (e.target.classList.contains('label-canvas')) {
                        this.selectedElementId = null;
                    }
                },

                // 放置元素
                dropElement(e) {
                    e.preventDefault();
                    const elementType = e.dataTransfer.getData('elementType');
                    if (!elementType) return;

                    // 获取画布位置
                    const canvas = document.getElementById('labelCanvas');
                    const rect = canvas.getBoundingClientRect();

                    // 计算相对于画布的位置（直接使用像素单位）
                    const x = (e.clientX - rect.left) / this.zoomLevel;
                    const y = (e.clientY - rect.top) / this.zoomLevel;

                    // 创建新元素
                    const newElement = this.createElement(elementType, x, y);
                    this.elements.push(newElement);
                    this.selectedElementId = newElement.id;
                },

                // 创建元素
                createElement(type, x, y) {
                    const element = {
                        id: this.elementCounter++,
                        type: type,
                        x: Math.min(Math.max(0, x), this.canvasWidth - 20),
                        y: Math.min(Math.max(0, y), this.canvasHeight - 10),
                        width: type === 'rectangle' ? 30 : type === 'label' ? 80 : type === 'qrcode' ? 100 : 150,
                        height: type === 'rectangle' ? 20 : type === 'label' ? 30 : type === 'qrcode' ? 100 : 50,
                        fontSize: 12,
                        scale: 1.0
                    };

                    // 确保元素位置在画布范围内
                    element.x = Math.min(element.x, this.canvasWidth - element.width);
                    element.y = Math.min(element.y, this.canvasHeight - element.height);

                    if (type === 'label') {
                        element.text = '文本标签';
                        element.fontBold = false; // 默认不加粗
                        element.fontItalic = false; // 默认不斜体
                        element.fontFamily = ''; // 默认字体族
                    } else if (type === 'rectangle') {
                        element.backgroundColor = '#000000'; // 默认背景色为黑色
                    } else if (type === 'qrcode') {
                        element.content = 'https://example.com'; // 默认二维码内容
                    } else if (type === 'barcode') {
                        element.content = '1234567890'; // 默认条形码内容
                        element.format = 'CODE128'; // 默认条形码格式
                    }

                    return element;
                },

                // 获取元素样式
                getElementStyle(element) {
                    const style = {
                        left: element.x + 'px',
                        top: element.y + 'px',
                        width: element.width + 'px',
                        height: element.height + 'px',
                        fontSize: element.fontSize + 'px',
                        transform: `scale(${element.scale})`,
                        transformOrigin: 'top left'
                    };

                    // 添加字体样式
                    if (element.type === 'label') {
                        if (element.fontFamily) {
                            style.fontFamily = element.fontFamily;
                        }
                        if (element.fontBold) {
                            style.fontWeight = 'bold';
                        }
                        if (element.fontItalic) {
                            style.fontStyle = 'italic';
                        }
                    }

                    return style;
                },

                // 选择元素
                selectElement(id, event) {
                    event.stopPropagation();
                    this.selectedElementId = id;

                    // 实现元素拖拽移动
                    const element = this.elements.find(el => el.id === id);
                    if (!element) return;

                    const canvas = document.getElementById('labelCanvas');
                    const startX = event.clientX;
                    const startY = event.clientY;
                    const startElementX = element.x;
                    const startElementY = element.y;

                    const moveHandler = (moveEvent) => {
                        const dx = (moveEvent.clientX - startX) / this.zoomLevel;
                        const dy = (moveEvent.clientY - startY) / this.zoomLevel;

                        element.x = Math.max(0, Math.min(this.canvasWidth - element.width, startElementX + dx));
                        element.y = Math.max(0, Math.min(this.canvasHeight - element.height, startElementY + dy));
                    };

                    const upHandler = () => {
                        document.removeEventListener('mousemove', moveHandler);
                        document.removeEventListener('mouseup', upHandler);
                    };

                    document.addEventListener('mousemove', moveHandler);
                    document.addEventListener('mouseup', upHandler);
                },

                // 编辑元素
                editElement(element) {
                    if (element.type === 'label') {
                        this.$prompt('请输入文本内容', '编辑文本', {
                            inputValue: element.text,
                            confirmButtonText: '确定',
                            cancelButtonText: '取消'
                        }).then(({ value }) => {
                            element.text = value;
                        }).catch(() => {
                            // 取消操作
                        });
                    }
                },

                // 删除元素
                deleteElement() {
                    if (!this.selectedElementId) return;

                    this.$confirm('确定要删除选中的元素吗？', '删除确认', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }).then(() => {
                        const index = this.elements.findIndex(el => el.id === this.selectedElementId);
                        if (index !== -1) {
                            this.elements.splice(index, 1);
                            this.selectedElementId = null;
                        }
                    }).catch(() => {
                        // 取消操作
                    });
                },

                // 清空画布
                clearCanvas() {
                    this.$confirm('确定要清空整个画布吗？此操作不可恢复。', '清空确认', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }).then(() => {
                        this.elements = [];
                        this.selectedElementId = null;
                    }).catch(() => {
                        // 取消操作
                    });
                },

                // 导出布局
                exportLayout() {
                    const layoutData = {
                        elements: this.elements,
                        height: this.canvasHeight,
                        width: this.canvasWidth,
                        createdAt: new Date().toISOString()
                    };

                    const blob = new Blob([JSON.stringify(layoutData, null, 2)], {
                        type: 'application/json;charset=utf-8'
                    });

                    saveAs(blob, 'label-layout.json');
                    this.$message.success('布局已导出');
                },

                // 导入布局
                importLayout(file) {
                    const reader = new FileReader();
                    reader.onload = (e) => {
                        try {
                            const layoutData = JSON.parse(e.target.result);
                            if (layoutData.elements && Array.isArray(layoutData.elements)) {
                                this.elements = layoutData.elements;
                                this.canvasHeight = layoutData.height;
                                this.canvasWidth = layoutData.width;
                                this.elementCounter = Math.max(...layoutData.elements.map(el => el.id), 0) + 1;
                                this.$message.success('布局导入成功');
                            } else {
                                this.$message.error('无效的布局文件格式');
                            }
                        } catch (error) {
                            this.$message.error('解析布局文件失败：' + error.message);
                        }
                    };
                    reader.readAsText(file.raw);
                },

                // 放大
                zoomIn() {
                    this.zoomLevel = Math.min(2, this.zoomLevel + 0.1);
                    this.updateCanvasScale();
                },

                // 缩小
                zoomOut() {
                    this.zoomLevel = Math.max(0.5, this.zoomLevel - 0.1);
                    this.updateCanvasScale();
                },

                // 重置缩放
                resetZoom() {
                    this.zoomLevel = 1;
                    this.updateCanvasScale();
                },

                // 更新画布缩放
                updateCanvasScale() {
                    const canvas = document.getElementById('labelCanvas');
                    if (canvas) {
                        canvas.style.transform = `scale(${this.zoomLevel})`;
                        canvas.style.transformOrigin = 'center top';
                    }
                },

                // 重置元素缩放
                resetElementScale() {
                    if (this.selectedElement) {
                        this.$set(this.selectedElement, 'scale', 1.0);
                    }
                },

                // 开始调整大小
                startResize(id, direction, event) {
                    event.stopPropagation();
                    const element = this.elements.find(el => el.id === id);
                    if (!element) return;

                    const startX = event.clientX;
                    const startY = event.clientY;
                    const startWidth = element.width;
                    const startHeight = element.height;
                    const startXPos = element.x;
                    const startYPos = element.y;

                    const moveHandler = (moveEvent) => {
                        const dx = (moveEvent.clientX - startX) / this.zoomLevel;
                        const dy = (moveEvent.clientY - startY) / this.zoomLevel;

                        switch (direction) {
                            case 'se': // 右下
                                element.width = Math.max(1, startWidth + dx);
                                element.height = Math.max(1, startHeight + dy);
                                break;
                            case 'sw': // 左下
                                element.width = Math.max(1, startWidth - dx);
                                element.height = Math.max(1, startHeight + dy);
                                element.x = Math.max(0, startXPos + dx);
                                break;
                            case 'ne': // 右上
                                element.width = Math.max(1, startWidth + dx);
                                element.height = Math.max(1, startHeight - dy);
                                element.y = Math.max(0, startYPos + dy);
                                break;
                            case 'nw': // 左上
                                element.width = Math.max(1, startWidth - dx);
                                element.height = Math.max(1, startHeight - dy);
                                element.x = Math.max(0, startXPos + dx);
                                element.y = Math.max(0, startYPos + dy);
                                break;
                        }

                        // 确保元素不会超出画布边界
                        element.x = Math.max(0, Math.min(element.x, this.canvasWidth - element.width));
                        element.y = Math.max(0, Math.min(element.y, this.canvasHeight - element.height));
                    };

                    const upHandler = () => {
                        document.removeEventListener('mousemove', moveHandler);
                        document.removeEventListener('mouseup', upHandler);
                    };

                    document.addEventListener('mousemove', moveHandler);
                    document.addEventListener('mouseup', upHandler);
                },

                // 键盘事件处理
                handleKeyDown(event) {
                    // Delete键删除选中元素
                    if (event.key === 'Delete' && this.selectedElementId) {
                        this.deleteElement();
                    }
                    // Ctrl+C 复制元素
                    else if (event.ctrlKey && event.key === 'c' && this.selectedElementId) {
                        event.preventDefault();
                        this.copyElement();
                    }
                    // Ctrl+V 粘贴元素
                    else if (event.ctrlKey && event.key === 'v') {
                        event.preventDefault();
                        this.pasteElement();
                    }
                },

                // 复制元素
                copyElement() {
                    if (!this.selectedElementId) return;

                    const element = this.elements.find(el => el.id === this.selectedElementId);
                    if (element) {
                        // 深拷贝元素对象
                        this.clipboardElement = JSON.parse(JSON.stringify(element));
                        this.$message.success('元素已复制到剪贴板');
                    }
                },

                // 粘贴元素
                pasteElement() {
                    if (!this.clipboardElement) {
                        this.$message.warning('剪贴板中没有元素');
                        return;
                    }

                    // 创建新元素，基于剪贴板中的元素
                    const newElement = JSON.parse(JSON.stringify(this.clipboardElement));
                    newElement.id = this.elementCounter++;

                    // 将新元素位置稍微偏移，避免完全重叠
                    newElement.x = Math.min(newElement.x + 10, this.canvasWidth - newElement.width);
                    newElement.y = Math.min(newElement.y + 10, this.canvasHeight - newElement.height);

                    this.elements.push(newElement);
                    this.selectedElementId = newElement.id;
                    this.$message.success('元素已粘贴');
                },
            }
        });
    </script>
</body>

</html>